export 'dio/dio.dart';
import 'package:xanno/src/anno/utils/base.dart';

class Interface extends GBase {
  /// baseUrl
  final String? host;

  const Interface({this.host}) : super();
}

class HttpMethod {
  static const String get = 'GET';
  static const String post = 'POST';
  static const String patch = 'PATCH';
  static const String put = 'PUT';
  static const String delete = 'DELETE';
  static const String head = 'HEAD';
  static const String options = 'OPTIONS';
}

abstract class Method {
  ///custom host
  final String? host;

  ///method
  final String method;

  ///url
  final String? url;

  const Method({this.host, required this.method, this.url = ''});
}

class GET extends Method {
  const GET({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.get, url: url);
}

class POST extends Method {
  const POST({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.post, url: url);
}

class PATCH extends Method {
  const PATCH({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.patch, url: url);
}

class PUT extends Method {
  const PUT({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.put, url: url);
}

class DELETE extends Method {
  const DELETE({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.delete, url: url);
}

class HEAD extends Method {
  const HEAD({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.head, url: url);
}

class OPTIONS extends Method {
  const OPTIONS({
    String? host,
    String? url,
  }) : super(host: host, method: HttpMethod.options, url: url);
}

//class Options {
//  final Map<String, dynamic> value;
//
//  const Options([this.value]);
//}

/// Adds headers specified in the [value] map.
class Headers {
  final Map<String, dynamic>? value;

  const Headers([this.value]);
}

/// Replaces the header with the value of its target.
///
/// Header parameters may be `null` which will omit them from the request.
class Header {
  final String value;

  const Header(this.value);
}

/// Use this annotation on a service method param when you want to directly control the request body
/// of a POST/PUT request (instead of sending in as request parameters or form-style request
/// body).
///
/// Body parameters may not be `null`.
class Body {
  const Body();
}

/// Named pair for a form request.
///
/// ```
/// @POST("/post")
/// Future<String> example(
///   @Field() int foo,
///   @Field("bar") String barbar},
/// )
/// ```
/// Calling with `foo.example("Bob Smith", "President")` yields a request body of
/// `foo=Bob+Smith&bar=President`.
class Field {
  final String? value;

  const Field([this.value]);
}

/// Named replacement in a URL path segment.
///
/// Path parameters may not be `null`.
class Path {
  final String? value;

  const Path([this.value]);
}

/// Query parameter appended to the URL.
///
/// Simple Example:
///
///```
/// @GET("/get")
/// Future<String> foo(@Query('bar') String query)
///```
/// Calling with `foo.friends(1)` yields `/get?bar=1`.
class Query {
  final String value;
  final bool encoded;

  const Query(this.value, {this.encoded = false});
}

/// Query parameter keys and values appended to the URL.
///
/// A `null` value for the map, as a key, or as a value is not allowed.
class Queries {
  final bool encoded;

  const Queries({this.encoded = false});
}

/// Denotes that the request body will use form URL encoding. Fields should be declared as
/// parameters and annotated with [Field].
///
/// Requests made with this annotation will have `application/x-www-form-urlencoded` MIME
/// type. Field names and values will be UTF-8 encoded before being URI-encoded in accordance to
class FormUrlEncoded {
  final mime = 'application/x-www-form-urlencoded';

  const FormUrlEncoded();
}

/// Denotes that the request body is multi-part. Parts should be declared as parameters and
/// annotated with [Part].
class MultiPart {
  const MultiPart();
}

/// Denotes a single part of a multi-part request.
/// Part parameters may not be null.
/// ```
/// @POST("/post")
/// @MultiPart()
/// Future<String> example(
///   @Part() int foo,
///   { @Part(name: "bar") String barbar,
///     @Part(contentType:'application/json') File file
///   },
/// )
/// ```
class Part {
  final String? value;
  final String? name;

  /// If this field is a file, optionally specify it's name. otherwise the name
  /// will be derived from the actual file.
  final String? fileName;

  // To identify the content type of a file
  final String? contentType;

  const Part({this.value, this.name, this.fileName, this.contentType});
}
